package cn.edu.nju.ws.sview.rdf.canonicalization.labeled;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Statement;

/**
 * @author Gong Cheng
 * 
 */
public class LabeledRDFGraph {
	protected ArrayList<Statement> statements = null;

	protected HashMap<RDFNode, LabeledResource> resource2LabeledResource = null;

	protected ArrayList<ArrayList<LabeledResource>> labeledStatements = null;

	/**
	 * Initialize
	 * 
	 * @param statements
	 *            Statements to be labeled
	 */
	public LabeledRDFGraph(ArrayList<Statement> statements) {
		this.statements = statements;
	}

	/**
	 * Construct the graph
	 * 
	 */
	public void construct() {
		this.resource2LabeledResource = new HashMap<RDFNode, LabeledResource>();
		this.labeledStatements = new ArrayList<ArrayList<LabeledResource>>(
				this.statements.size());

		for (Statement stmt : this.statements) {
			RDFNode subj = stmt.getSubject();
			LabeledResource lSubj = this.resource2LabeledResource.get(subj);
			if (lSubj == null) {
				lSubj = new LabeledResource(subj);
				this.resource2LabeledResource.put(subj, lSubj);
			}
			RDFNode pred = stmt.getPredicate();
			LabeledResource lPred = this.resource2LabeledResource.get(pred);
			if (lPred == null) {
				lPred = new LabeledResource(pred);
				this.resource2LabeledResource.put(pred, lPred);
			}
			RDFNode obj = stmt.getObject();
			LabeledResource lObj = this.resource2LabeledResource.get(obj);
			if (lObj == null) {
				lObj = new LabeledResource(obj);
				this.resource2LabeledResource.put(obj, lObj);
			}

			ArrayList<LabeledResource> labeledStatement = new ArrayList<LabeledResource>(
					3);
			labeledStatement.add(lSubj);
			labeledStatement.add(lPred);
			labeledStatement.add(lObj);
			this.labeledStatements.add(labeledStatement);
		}
	}

	/**
	 * List all labeled resources
	 * 
	 * @return All labeled resources
	 */
	public Iterator<LabeledResource> listLabeledResources() {
		return this.resource2LabeledResource.values().iterator();
	}

	/**
	 * Get labeled statements
	 * 
	 * @return Labeled statements
	 */
	public ArrayList<ArrayList<LabeledResource>> getLabeledStatements() {
		return this.labeledStatements;
	}

	public void close() {
		this.statements = null;
		for (LabeledResource lr : this.resource2LabeledResource.values()) {
			lr.close();
		}
		this.resource2LabeledResource.clear();
		this.resource2LabeledResource = null;
		for (ArrayList<LabeledResource> labeledStatement : this.labeledStatements) {
			labeledStatement.clear();
		}
		this.labeledStatements.clear();
		this.labeledStatements = null;
	}
}